// 接口：抽象类（有抽象的也有非抽象） 接口必须都是抽象的（没有具体的实现）
// 接口的概念 就是描述数据的结构、或者形状的，定义好结构，再去针对结构来进行实现

// type 和 interface 区别
// 一般情况下 描述对象，类 我们采用interface更多一些，interface无法声明联合类型
// type 可以快速声明类型 联合类型，工具类型只能采用type，type不能重名
// type用的更多，能用type就type 不能用interface。 复杂类型采用type

// 1）接口可以描述对象结构 （字可以赋予给父）
interface IPersoon {
  username: string // 类型，不是具体实现
  age: number
}

// 字可以赋予给父亲。我们需要把一个值赋予给另一个值。如果是声明的必须一致
// let obj = {
//   username: 'nick',
//   age: 33,
//   address: 'location'
// }
// let person:IPersoon = obj

class Person {
  username!: string // 类型，不是具体实现
  age!: number
}
class Child extends Person {
  address!: string
}

let person: Person = new Child()

// 2）接口可以描述函数
interface ICounter {
  (): number
  count: number
}
// const 标识此值不能修改 let 可以修改的（如果给函数增加类型定义 函数不能被修改时只能用const）
const counter:ICounter = () => {
  return counter.count++
}
counter.count = 0
counter()

// 1）可以通过?表示接口的属性 可有可无
// interface IVeg {
//   name: string
//   taste: string
//   size: number
//   color?: string
// }

// const veg:IVeg = {
//   name: '西红柿',
//   taste: '甜',
//   size: 50
// }
// 2）断言的方式来进行赋值，用的最多 as IVeg
// 3）接口的合并 同名的会进行合并，自定义类型的时候 会使用。自己的业务逻辑用的比较少
// 4）可以扩展一个新类型 再来使用。可以扩展属性
// 5）任意类型 随机的属性 数字描述索引的（除了必有的属性之外，其他任意）
// 6）兼容性
interface IVeg {
  readonly name: string // 只读
  taste: string
  size: number
}
interface IVegetable extends IVeg {
  color?: string,
  [key: string]: any // 任意接口 key 随意，值随意
  [key: number]: any
}
const veg:IVegetable = {
  name: '西红柿',
  taste: '甜',
  size: 50,
  color: '红色',
  a: 1,
  b: '2',
  [Symbol()]: 'ABC'
}

interface IArray { // 索引接口
  [key: number]: any
  push(): void
}
let arr:IArray = {
  0: 1,
  1: 2,
  push: () => {}
}

interface ResponseData {
  username: string
  token: string
}
interface ReturnVal {
  code: number
  data: ResponseData
}

// 通过索引访问符 来获取内部类型

type ICode = ReturnVal['code']
type IUSername = ReturnVal['data']['username'] // 可以用于取值的类型
type IKeys = ReturnVal[keyof ReturnVal] // 取值的类型，可以采用这种方式

// 接口可以实现，接口的实现都是通过类来实现

interface Speakable {

}

class Speaker {
  
}

export {}
